import domain.Person;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 获取成员方法们：
 * Method[] getMethods()：获取所有public修饰的成员方法
 * Method getMethod(String name, Class<?>... parameterTypes)：获取指定名称的public修饰的成员方法
 * Method[] getDeclaredMethods()：获取所有的成员方法，不考虑修饰符
 * Method getDeclaredMethod(String name, Class<?>... parameterTypes)：获取指定名称的成员变量，对于非public修饰的方法，先调用setAccessible(true)忽略访问权限修饰符的安全检查，否则抛异常。
 * 执行方法：
 * Object invoke(Object obj, Object... args)
 * 获取方法名称：
 * String getName:获取方法名
 */
public class ClassFunction_Method {
    public static void main(String[] args) {
        try {
            //0.获取Person类的Class对象
            Class personClass = Person.class;
            //1.Method getMethod(String name, Class<?>... parameterTypes)：获取指定名称和参数列表的public修饰的成员方法，参数要传对应参数类型的Class对象。
            Method eat_method = personClass.getMethod("eat");//空参数
            Method eat_method_with_parameters = personClass.getMethod("eat", String.class);//有参数
            Person p = new Person();
            //2.Object invoke(Object obj, Object... args)：传递需要执行方法的对象，并传递方法的参数，执行方法。
            eat_method.invoke(p);//eat...
            eat_method_with_parameters.invoke(p,"Watermelon");//eating Watermelon

            //3.Method[] getMethods()：获取所有public修饰的成员方法，继承了父类的方法也会被打印
            Method[] methods = personClass.getMethods();
            for (Method method : methods) {
                System.out.println(method);
                //输出结果：可以看到Person类的父类Object类中的部分方法也被打印出来了
                //public java.lang.String domain.Person.toString()
                //public java.lang.String domain.Person.getName()
                //public void domain.Person.setName(java.lang.String)
                //public void domain.Person.eat()
                //public void domain.Person.eat(java.lang.String)
                //public int domain.Person.getAge()
                //public void domain.Person.setAge(int)
                //public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
                //public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
                //public final void java.lang.Object.wait() throws java.lang.InterruptedException
                //public boolean java.lang.Object.equals(java.lang.Object)
                //public native int java.lang.Object.hashCode()
                //public final native java.lang.Class java.lang.Object.getClass()
                //public final native void java.lang.Object.notify()
                //public final native void java.lang.Object.notifyAll()
            }
            //4.String getName()：获取方法名称
            for (Method method : methods) {
                System.out.println(method.getName());
                //输出结果：
                //toString getName setName getAge eat eat setAge wait
                //wait wait equals hashCode getClass notify notifyAll
            }
            //5.String getName()：获取全类名
            String className = personClass.getName();
            System.out.println(className);//domain.Person
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
